﻿using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using NielsHebling.UnitTestResultViewerForSL.Core.Data;

namespace NielsHebling.UnitTestResultViewerForSL.Controls
{    
    [TemplatePart(Name = ResultList.ToggleShowSucceededPartName, Type = typeof(ToggleButton))]
    [TemplatePart(Name = ResultList.ToggleShowFailedPartName, Type = typeof(ToggleButton))]
    [TemplatePart(Name = ResultList.ToggleShowIgnoredPartName, Type = typeof(ToggleButton))]
    [TemplatePart(Name = ResultList.ButtonRunTestPartName, Type = typeof(Button))]
    [TemplatePart(Name = ResultList.ComboBoxAssembliesPartName, Type = typeof(ComboBox))]
    [TemplatePart(Name = ResultList.ButtonRefreshAssembliesPartName, Type = typeof(Button))]
    public class ResultList : Control
    {
        #region TemplateParts        
        private const string ToggleShowSucceededPartName = "PART_ToggleShowSucceeded";
        private const string ToggleShowIgnoredPartName = "PART_ToggleShowIgnored";
        private const string ToggleShowFailedPartName = "PART_ToggleShowFailed";
        private const string ButtonRunTestPartName = "PART_ButtonRunTest";
        private const string ComboBoxAssembliesPartName = "PART_ComboBoxAssemblies";        
        private const string ButtonRefreshAssembliesPartName = "PART_ButtonRefreshAssemblies";
        #endregion

        #region Member
        private ToggleButton _toggleShowSucceeded;
        private ToggleButton _toggleShowIgnored;
        private ToggleButton _toggleShowFailed;
        private Button _buttonRunTest;
        private Button _buttonRefreshAssemblies;
        private ComboBox _comboBoxAssemblies;
        private ObservableCollection<string> _showFilterSelection;
        private ICollectionView _view;        
        #endregion

        #region UI Text
        #region DependencyProperty ToggleButtonShowSuccessText
        public string ToggleShowSuccessText
        {
            get { return (string)GetValue(ToggleShowSuccessTextProperty); }
            set { SetValue(ToggleShowSuccessTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ToggleShowSuccessText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ToggleShowSuccessTextProperty =
            DependencyProperty.Register("ToggleShowSuccessText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Passed"));
        #endregion

        #region DependencyProperty ToggleShowFailedText
        public string ToggleShowFailedText
        {
            get { return (string)GetValue(ToggleShowFailedTextProperty); }
            set { SetValue(ToggleShowFailedTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ToggleShowFailedText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ToggleShowFailedTextProperty =
            DependencyProperty.Register("ToggleShowFailedText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Failed"));
        #endregion

        #region DependencyProperty ToggleShowIgnoredText
        public string ToggleShowIgnoredText
        {
            get { return (string)GetValue(ToggleShowIgnoredTextProperty); }
            set { SetValue(ToggleShowIgnoredTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ToggleShowIgnoredText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ToggleShowIgnoredTextProperty =
            DependencyProperty.Register("ToggleShowIgnoredText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Ignored"));
        #endregion

        #region DependencyProperty LabelFilterByTagText
        public string LabelFilterByTagText
        {
            get { return (string)GetValue(LabelFilterByTagTextProperty); }
            set { SetValue(LabelFilterByTagTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LabelFilterByTagText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelFilterByTagTextProperty =
            DependencyProperty.Register("LabelFilterByTagText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Tags:"));
        #endregion

        #region DependencyProperty ButtonRunTestText
        public string ButtonRunTestText
        {
            get { return (string)GetValue(ButtonRunTestTextProperty); }
            set { SetValue(ButtonRunTestTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ButtonRunTestText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ButtonRunTestTextProperty =
            DependencyProperty.Register("ButtonRunTestText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Run Test"));
        #endregion

        #region DependencyProperty ColumnHeaderStatusText
        public string ColumnHeaderStatusText
        {
            get { return (string)GetValue(ColumnHeaderStatusTextProperty); }
            set { SetValue(ColumnHeaderStatusTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ColumnHeaderStatus.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColumnHeaderStatusTextProperty =
            DependencyProperty.Register("ColumnHeaderStatusText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Status"));
        #endregion

        #region DependencyProperty ColumnHeaderMessageText
        public string ColumnHeaderMessageText
        {
            get { return (string)GetValue(ColumnHeaderMessageTextProperty); }
            set { SetValue(ColumnHeaderMessageTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ColumnHeaderMessageText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColumnHeaderMessageTextProperty =
            DependencyProperty.Register("ColumnHeaderMessageText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Message"));
        #endregion       

        #region DependencyProperty ColumnHeaderTestSourceText
        public string ColumnHeaderTestSourceText
        {
            get { return (string)GetValue(ColumnHeaderTestSourceTextProperty); }
            set { SetValue(ColumnHeaderTestSourceTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ColumnHeaderTestClassText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColumnHeaderTestSourceTextProperty =
            DependencyProperty.Register("ColumnHeaderTestSourceText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Test Source"));
        #endregion

        #region DependencyProperty ColumnHeaderDurationText
        public string ColumnHeaderDurationText
        {
            get { return (string)GetValue(ColumnHeaderDurationTextProperty); }
            set { SetValue(ColumnHeaderDurationTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ColumnHeaderDurationText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColumnHeaderDurationTextProperty =
            DependencyProperty.Register("ColumnHeaderDurationText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Duration"));
        #endregion

        #region DependencyProperty LabelTestRunSummaryText
        public string LabelTestRunSummaryText
        {
            get { return (string)GetValue(LabelTestRunSummaryTextProperty); }
            set { SetValue(LabelTestRunSummaryTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LabelTestRunSummaryText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelTestRunSummaryTextProperty =
            DependencyProperty.Register("LabelTestRunSummaryText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Test run results"));
        #endregion

        #region DependencyProperty LabelFilterByAssemblyText
        public string LabelFilterByAssemblyText
        {
            get { return (string)GetValue(LabelFilterByAssemblyTextProperty); }
            set { SetValue(LabelFilterByAssemblyTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LabelFilterByAssemblyText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelFilterByAssemblyTextProperty =
            DependencyProperty.Register("LabelFilterByAssemblyText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Assembly:"));
        #endregion

        #region DependencyProperty CheckBoxRunOnBuildDoneText
        public string CheckBoxRunOnBuildDoneText
        {
            get { return (string)GetValue(CheckBoxRunOnBuildDoneTextProperty); }
            set { SetValue(CheckBoxRunOnBuildDoneTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CheckBoxRunOnBuildDoneText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CheckBoxRunOnBuildDoneTextProperty =
            DependencyProperty.Register("CheckBoxRunOnBuildDoneText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Run test on build done"));
        #endregion

        #region DependencyProperty ButtonRefreshAssembliesText
        public string ButtonRefreshAssembliesText
        {
            get { return (string)GetValue(ButtonRefreshAssembliesTextProperty); }
            set { SetValue(ButtonRefreshAssembliesTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ButtonRefreshAssembliesText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ButtonRefreshAssembliesTextProperty =
            DependencyProperty.Register("ButtonRefreshAssembliesText", typeof(string), typeof(ResultList), new UIPropertyMetadata("Refresh"));        
        #endregion

        #endregion

        #region DependencyProperty Items
        [Category("ResultList")]
        public ObservableCollection<ViewResultData> Items
        {
            get { return (ObservableCollection<ViewResultData>)GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Items.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemsProperty =
            DependencyProperty.Register("Items", typeof(ObservableCollection<ViewResultData>), typeof(ResultList), new UIPropertyMetadata(null));
        
        #endregion

        #region DependencyProperty AssemblyItems
        public IEnumerable AssemblyItems
        {
            get { return (IEnumerable)GetValue(AssemblyItemsProperty); }
            set { SetValue(AssemblyItemsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AssemblyItems.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AssemblyItemsProperty =
            DependencyProperty.Register("AssemblyItems", typeof(IEnumerable), typeof(ResultList), new UIPropertyMetadata(null));
        #endregion

        #region DependencyProperty SelectedAssemblyItem
        public ProjectXapItem SelectedAssemblyItem
        {
            get { return (ProjectXapItem)GetValue(SelectedAssemblyItemProperty); }
            set { SetValue(SelectedAssemblyItemProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedAssemblyItem.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedAssemblyItemProperty =
            DependencyProperty.Register("SelectedAssemblyItem", typeof(ProjectXapItem), typeof(ResultList), new UIPropertyMetadata(null));
        #endregion

        #region DepedencyProperty RunOnBuildDone
        public bool RunOnBuildDone
        {
            get { return (bool)GetValue(RunOnBuildDoneProperty); }
            set { SetValue(RunOnBuildDoneProperty, value); }
        }

        // Using a DependencyProperty as the backing store for RunOnBuildDone.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RunOnBuildDoneProperty =
            DependencyProperty.Register("RunOnBuildDone", typeof(bool), typeof(ResultList), new UIPropertyMetadata(false));
        #endregion

        #region DependencyProperty IsRunning
        public bool IsRunning
        {
            get { return (bool)GetValue(IsRunningProperty); }
            set { SetValue(IsRunningProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsRunning.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsRunningProperty =
            DependencyProperty.Register("IsRunning", typeof(bool), typeof(ResultList), new UIPropertyMetadata(false));
        #endregion        

        #region DependencyProperty ProgressValue
        public int ProgressValue
        {
            get { return (int)GetValue(ProgressValueProperty); }
            set { SetValue(ProgressValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ProgressValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ProgressValueProperty =
            DependencyProperty.Register("ProgressValue", typeof(int), typeof(ResultList), new UIPropertyMetadata(0));
        #endregion

        #region DependencyProperty MaxProgressValue
        public int MaxProgressValue
        {
            get { return (int)GetValue(MaxProgressValueProperty); }
            set { SetValue(MaxProgressValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MaxProgressValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxProgressValueProperty =
            DependencyProperty.Register("MaxProgressValue", typeof(int), typeof(ResultList), new UIPropertyMetadata(0));
        #endregion

        public event RoutedEventHandler TriggerTest;
        public event RoutedEventHandler RefreshAssemblies;

        static ResultList()
        {            
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ResultList), new FrameworkPropertyMetadata(typeof(ResultList)));            
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (_showFilterSelection == null)
            {
                _showFilterSelection = new ObservableCollection<string>();                
            }            

            if (_toggleShowFailed == null)
            {
                _toggleShowFailed = GetTemplateChild(ResultList.ToggleShowFailedPartName) as ToggleButton;

                _toggleShowFailed.Checked -= new RoutedEventHandler(_toggleShow_Checked);
                _toggleShowFailed.Unchecked -= new RoutedEventHandler(_toggleShow_Unchecked);

                _toggleShowFailed.Checked += new RoutedEventHandler(_toggleShow_Checked);
                _toggleShowFailed.Unchecked += new RoutedEventHandler(_toggleShow_Unchecked);

                _toggleShowFailed.IsChecked = true;                    
            }

            if (_toggleShowIgnored == null)
            {
                _toggleShowIgnored = GetTemplateChild(ResultList.ToggleShowIgnoredPartName) as ToggleButton;

                _toggleShowIgnored.Checked -= new RoutedEventHandler(_toggleShow_Checked);
                _toggleShowIgnored.Unchecked -= new RoutedEventHandler(_toggleShow_Unchecked);

                _toggleShowIgnored.Checked += new RoutedEventHandler(_toggleShow_Checked);
                _toggleShowIgnored.Unchecked += new RoutedEventHandler(_toggleShow_Unchecked);

                _toggleShowIgnored.IsChecked = true;                    
            }

            if (_toggleShowSucceeded == null)
            {
                _toggleShowSucceeded = GetTemplateChild(ResultList.ToggleShowSucceededPartName) as ToggleButton;

                _toggleShowSucceeded.Checked -= new RoutedEventHandler(_toggleShow_Checked);
                _toggleShowSucceeded.Unchecked -= new RoutedEventHandler(_toggleShow_Unchecked);

                _toggleShowSucceeded.Checked += new RoutedEventHandler(_toggleShow_Checked);
                _toggleShowSucceeded.Unchecked += new RoutedEventHandler(_toggleShow_Unchecked);

                _toggleShowSucceeded.IsChecked = true;
            }            

            if (_buttonRunTest == null)
            {
                _buttonRunTest = GetTemplateChild(ResultList.ButtonRunTestPartName) as Button;
                
                _buttonRunTest.Click -= new RoutedEventHandler(_buttonRunTest_Click);                
                _buttonRunTest.Click +=new RoutedEventHandler(_buttonRunTest_Click);                
            }

            if (_buttonRefreshAssemblies == null)
            {
                _buttonRefreshAssemblies = GetTemplateChild(ResultList.ButtonRefreshAssembliesPartName) as Button;

                _buttonRefreshAssemblies.Click -= new RoutedEventHandler(_buttonRefreshAssemblies_Click);
                _buttonRefreshAssemblies.Click += new RoutedEventHandler(_buttonRefreshAssemblies_Click);
            }

            if (_comboBoxAssemblies == null)
            {
                _comboBoxAssemblies = GetTemplateChild(ResultList.ComboBoxAssembliesPartName) as ComboBox;
                _comboBoxAssemblies.SelectionChanged += new SelectionChangedEventHandler(_comboBoxAssemblies_SelectionChanged);
            }

            if (_view == null)
            {
                _view = CollectionViewSource.GetDefaultView(Items);
                if (_view != null)
                {
                    _view.Filter = new Predicate<object>(ApplyFilter);
                }
            }            
        }

        void _buttonRefreshAssemblies_Click(object sender, RoutedEventArgs e)
        {
            if (RefreshAssemblies != null)
            {
                RefreshAssemblies(sender, e);
            }
        }              

        void _comboBoxAssemblies_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.SelectedAssemblyItem = _comboBoxAssemblies.SelectedItem as ProjectXapItem;
        }
        

        void _buttonRunTest_Click(object sender, RoutedEventArgs e)
        {
            if (TriggerTest != null)
            {
                TriggerTest(sender, e);
            }
        }

        #region Filter
        void _toggleShow_Unchecked(object sender, RoutedEventArgs e)
        {
            ToggleButton instance = sender as ToggleButton;
            if (_showFilterSelection.Contains(instance.Tag as String))
            {                                
                string selectedType = instance.Tag as String;
                _showFilterSelection.Remove(selectedType);
                _view = CollectionViewSource.GetDefaultView(Items);
                if (_view != null)
                {
                    _view.Filter = new Predicate<object>(ApplyFilter);
                }
            }            
        }

        void _toggleShow_Checked(object sender, RoutedEventArgs e)
        {
            ToggleButton instance = sender as ToggleButton;
            if (!_showFilterSelection.Contains(instance.Tag as String))
            {
                string selectedType = instance.Tag as String;
                _showFilterSelection.Add(selectedType);
                _view = CollectionViewSource.GetDefaultView(Items);
                if (_view != null)
                {
                    _view.Filter = new Predicate<object>(ApplyFilter);
                }
            }            
        }

        private bool ApplyFilter(object data)
        {
            ViewResultData item = data as ViewResultData;
            if (item == null || !_showFilterSelection.Contains(item.Result))
            {
                return false;                    
            }
            return true;
        }  
        #endregion
    }
}
